-- ************************************************************************** --
-- * TitanKillTimer.lua                                                         
-- *                                                                        
-- * By: Rothpada                                                           
-- ************************************************************************** --

local TITAN_KT_ID = "TitanKillTimer";
local L = LibStub("AceLocale-3.0"):GetLocale("TitanKillTimer", true)
local AceTimer = LibStub("AceTimer-3.0"); 

local IS_DEBUGGING = true;
local MobTable = {};


-- Ref: http://lua-users.org/wiki/SortedIteration

local function __genOrderedIndex( t )
    local orderedIndex = {}
    for key in pairs(t) do
        table.insert( orderedIndex, key )
    end
    table.sort( orderedIndex )
    return orderedIndex
end

local function orderedNext(t, state)
    -- Equivalent of the next function, but returns the keys in the alphabetic
    -- order. We use a temporary ordered key table that is stored in the
    -- table being iterated.

    --print("orderedNext: state = "..tostring(state) )
    if state == nil then
        -- the first time, generate the index
        t.__orderedIndex = __genOrderedIndex( t )
        key = t.__orderedIndex[1]
        return key, t[key]
    end
    -- fetch the next value
    key = nil
    for i = 1,table.getn(t.__orderedIndex) do
        if t.__orderedIndex[i] == state then
            key = t.__orderedIndex[i+1]
        end
    end

    if key then
        return key, t[key]
    end

    -- no more value to return, cleanup
    t.__orderedIndex = nil
    return
end

local function orderedPairs(t)
    -- Equivalent of the pairs() function on tables. Allows to iterate
    -- in order
    return orderedNext, t, nil
end

local function getETD(mobGUID)	
	local firstt = time();
	local lastt = 0;
	local firsthp = 1;
	local lasthp = 1;
	
	
	if ( MobTable[mobGUID] ~= nil ) then
		table.sort(MobTable[mobGUID].history);
		for t,hp in pairs(MobTable[mobGUID].history) do
			if ( t < firstt ) then
				firstt = t;
				firsthp = hp;
			elseif ( t > lastt ) then
				lastt = t;
				lasthp = hp;
			end
		end
		local deltat = lastt - firstt;
		local deltahp = firsthp - lasthp;
		local etd = (MobTable[mobGUID].currentHealth/MobTable[mobGUID].maxHealth) / (deltahp / deltat);
		TitanKillTimer_debug("dt="..deltat..",h0="..firsthp..",hn="..lasthp..",dh="..deltahp..",etd="..TitanUtils_GetAbbrTimeText(ceil(etd)));
		return etd;
	end
end

local function updateMob(mobGUID, timestamp, unitHealthDelta)
	MobTable[mobGUID].currentHealth = MobTable[mobGUID].currentHealth + unitHealthDelta;
	MobTable[mobGUID].history[timestamp] = MobTable[mobGUID].currentHealth / MobTable[mobGUID].maxHealth;
end

local function removeMob(mobGUID)
	MobTable[mobGUID] = nil;
end

local function updateTarget()
	if ( UnitCanAttack("player", "target") ) then
		local mobGUID = UnitGUID("target");
		if ( not UnitIsDead("target") ) then
			if ( MobTable[mobGUID] == nil ) then
				MobTable[mobGUID] = {};
				MobTable[mobGUID].history = {};
				MobTable[mobGUID].name = UnitName("target");
				MobTable[mobGUID].currentHealth = UnitHealth("target");
				MobTable[mobGUID].maxHealth = UnitHealthMax("target");
			end
			TitanKillTimer_debug("Updating "..UnitName("target").." ("..mobGUID.."): t="..time().." %="..(UnitHealth("target") / MobTable[mobGUID].maxHealth));
			updateMob(mobGUID, time(), UnitHealth("target") - MobTable[mobGUID].currentHealth);
		end
	end
end

-- ************************************************************************** --
-- ******************************** Titan Functions ************************* --
-- ************************************************************************** --

function TitanPanelTitanKillTimerButton_OnLoad(self)
	self.registry = {
		id = TITAN_KT_ID,
		menuText = L["TITAN_KT_MENU_TEXT"],
		buttonTextFunction = "TitanPanelTitanKillTimerButton_GetButtonText",
		tooltipTitle = L["TITAN_KT_TOOLTIP_TITLE"],
		tooltipTextFunction = "TitanPanelTitanKillTimerButton_GetTooltipText",
		frequency = 1,
		savedVariables = {
			ShowLabelText = 1,
			ShowNumbers = 1,
			ShowColours = 1,
		}	
	};
		
	self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED");
	TitanKillTimer_output(TITAN_KT_ID.." by Rothpada (Shadow Council)");
	TitanPanelPluginHandle_OnUpdate({TITAN_KT_ID, TITAN_PANEL_UPDATE_ALL});
end

function TitanPanelTitanKillTimerButton_OnClick(self, button)

end

function TitanPanelTitanKillTimerButton_OnEvent(self, event, ...)
	local runUpdate = false;
	
	if ( event == "COMBAT_LOG_EVENT_UNFILTERED" ) then
		local timestamp, etype, sourceGUID, sourceName, sourceFlags, destGUID, destName, destFlags = select(1, ...);
		
		if ( etype == "UNIT_DIED" ) then
			TitanKillTimer_debug("Unit died: "..destName.." ("..destGUID..")");
			removeMob(destGUID);
			runUpdate = true;
		elseif ( InCombatLockdown() or UnitAffectingCombat("player") ) then
			if ( destGUID == UnitGUID("target") ) then
				updateTarget();
				runUpdate = true;
			end
		else
			MobTable = {};
			runUpdate = true;
		end
	end
	
	if runUpdate then
		TitanPanelButton_UpdateButton(TITAN_KT_ID);
		TitanPanelPluginHandle_OnUpdate({TITAN_KT_ID, TITAN_PANEL_UPDATE_ALL});
	end
end

function TitanPanelTitanKillTimerButton_GetButtonText(id)
	local label = L["TITAN_KT_LABEL"];
	
	local text = "---";
	if ( MobTable[UnitGUID("target")] ~= nil ) then
		text = TitanUtils_GetAbbrTimeText(ceil(getETD(UnitGUID("target"))));
	end
	
	return label, text;
end

function TitanPanelTitanKillTimerButton_GetTooltipText(self)
	local text = "";
	for mobGUID,mobTable in pairs(MobTable) do
		text = text..MobTable[mobGUID].name..": "..getETD(mobGUID).."\n"
	end
	return text.."\n"..L["TITAN_KT_HINT"];		
end

function TitanPanelRightClickMenu_PrepareTitanKillTimerMenu()
	TitanPanelRightClickMenu_AddTitle(TitanPlugins[TITAN_KT_ID].menuText);
	TitanPanelRightClickMenu_AddSpacer();
	
	TitanPanelRightClickMenu_AddSpacer();
	
 	TitanPanelRightClickMenu_AddToggleLabelText(TITAN_KT_ID);
		
	TitanPanelRightClickMenu_AddSpacer();
end

-- ************************************************************************** --
-- ******************************** User Functions ************************** --
-- ************************************************************************** --

function TitanKillTimer_debug(msg)
	if IS_DEBUGGING then
		TitanKillTimer_output(msg);
	end
end

function TitanKillTimer_output(msg)
    DEFAULT_CHAT_FRAME:AddMessage(msg, 1, 1, 1);
end


function TitanKillTimer_getColouredText(msg, colour)
	local colourCode = "";
	
	if ( colour == nil or colour == "default" ) then
		return msg;
	elseif ( colour == "red" ) then
		colourCode = "|cffff0000";
	elseif ( colour == "green" ) then
		colourCode = "|cff00ff00";
	elseif ( colour == "blue" ) then
		colourCode = "|cff0000ff";
	elseif ( colour == "yellow" ) then
		colourCode = "|cffffff00";
	elseif ( colour == "white" ) then
		colourCode = "|cffffffff";
	elseif ( colour == "black" ) then
		colourCode = "|cff000000";
	else
		colourCode = "|cff"..colour;
	end
        
	return colourCode..msg..FONT_COLOR_CODE_CLOSE;
end

